package com.yang.demo.comparison;

import com.yang.core.api.RestClient;
import com.yang.core.api.RestClientBuilder;
import com.yang.core.plugins.cache.CacheExtension;
import com.yang.core.plugins.monitoring.MonitoringExtension;
import com.yang.core.plugins.retry.RetryExtension;
import com.yang.core.config.RestClientProperties;
import lombok.extern.slf4j.Slf4j;

import java.time.Duration;
import java.util.Map;

/**
 * 功能对比测试
 * 展示不同配置下的性能和功能差异
 */
@Slf4j
public class FeatureComparison {

    public static void main(String[] args) {
        System.out.println("=== RestClient 功能对比测试 ===\n");

        try {
            // 1. 基础配置 vs 高级配置对比
            basicVsAdvancedComparison();

            // 2. 缓存功能对比
            cacheComparison();

            // 3. 重试功能对比
            retryComparison();

            // 4. 并发性能对比
            concurrencyComparison();

            // 5. 内存使用对比
            memoryUsageComparison();

        } catch (Exception e) {
            log.error("对比测试失败", e);
        }
    }

    /**
     * 基础配置 vs 高级配置对比
     */
    private static void basicVsAdvancedComparison() {
        System.out.println("1. 基础配置 vs 高级配置对比");
        System.out.println("=" + "=".repeat(50));

        // 基础配置客户端
        RestClient basicClient = RestClient.create();

        // 高级配置客户端
        RestClient advancedClient = RestClient.builder()
            .forHighPerformance()
            .baseUrl("https://httpbin.org")
            .enableCompression(true)
            .timeout(Duration.ofSeconds(30))
            .build();

        try {
            String testUrl = "https://httpbin.org/get";
            int iterations = 10;

            // 测试基础客户端
            long basicTotalTime = 0;
            for (int i = 0; i < iterations; i++) {
                long start = System.currentTimeMillis();
                var response = basicClient.get(testUrl);
                long end = System.currentTimeMillis();
                basicTotalTime += (end - start);
            }

            // 测试高级客户端
            long advancedTotalTime = 0;
            for (int i = 0; i < iterations; i++) {
                long start = System.currentTimeMillis();
                var response = advancedClient.get(testUrl);
                long end = System.currentTimeMillis();
                advancedTotalTime += (end - start);
            }

            System.out.printf("基础配置平均响应时间: %.2fms%n", (double)basicTotalTime / iterations);
            System.out.printf("高级配置平均响应时间: %.2fms%n", (double)advancedTotalTime / iterations);
            System.out.printf("性能提升: %.2f%%%n",
                ((double)(basicTotalTime - advancedTotalTime) / basicTotalTime) * 100);

        } finally {
            basicClient.close();
            advancedClient.close();
        }

        System.out.println();
    }

    /**
     * 缓存功能对比
     */
    private static void cacheComparison() {
        System.out.println("2. 缓存功能对比");
        System.out.println("=" + "=".repeat(50));

        // 无缓存客户端
        RestClient noCacheClient = RestClient.builder()
            .baseUrl("https://httpbin.org")
            .build();

        // 有缓存客户端
        RestClientProperties cacheProps = new RestClientProperties();
        cacheProps.getCache().setEnabled(true);
        cacheProps.getCache().setDefaultTtl(Duration.ofMinutes(5));

        CacheExtension cacheExtension = new CacheExtension(cacheProps.getCache());

        RestClient cachedClient = RestClient.builder()
            .baseUrl("https://httpbin.org")
            .addExtension(cacheExtension)
            .build();

        try {
            String testUrl = "/uuid";
            int iterations = 5;

            // 测试无缓存客户端
            long noCacheTotalTime = 0;
            for (int i = 0; i < iterations; i++) {
                long start = System.currentTimeMillis();
                var response = noCacheClient.get(testUrl);
                long end = System.currentTimeMillis();
                noCacheTotalTime += (end - start);
            }

            // 测试有缓存客户端
            long cachedTotalTime = 0;
            for (int i = 0; i < iterations; i++) {
                long start = System.currentTimeMillis();
                var response = cachedClient.get(testUrl);
                long end = System.currentTimeMillis();
                cachedTotalTime += (end - start);
            }

            System.out.printf("无缓存总耗时: %dms%n", noCacheTotalTime);
            System.out.printf("有缓存总耗时: %dms%n", cachedTotalTime);
            System.out.printf("缓存加速比: %.2fx%n", (double)noCacheTotalTime / cachedTotalTime);

        } finally {
            noCacheClient.close();
            cachedClient.close();
        }

        System.out.println();
    }

    /**
     * 重试功能对比
     */
    private static void retryComparison() {
        System.out.println("3. 重试功能对比");
        System.out.println("=" + "=".repeat(50));

        // 无重试客户端
        RestClient noRetryClient = RestClient.builder()
            .baseUrl("https://httpbin.org")
            .enableRetry(false)
            .build();

        // 有重试客户端
        RestClient retryClient = RestClient.builder()
            .baseUrl("https://httpbin.org")
            .enableRetry(true)
            .maxRetries(3)
            .retryDelay(Duration.ofMillis(500))
            .addExtension(new RetryExtension())
            .build();

        try {
            String failingUrl = "/status/500";

            // 测试无重试客户端
            int noRetrySuccess = 0;
            int noRetryAttempts = 10;

            for (int i = 0; i < noRetryAttempts; i++) {
                try {
                    var response = noRetryClient.get(failingUrl);
                    if (response.getStatusCode() == 200) {
                        noRetrySuccess++;
                    }
                } catch (Exception e) {
                    // 忽略异常，继续测试
                }
            }

            // 测试有重试客户端
            int retrySuccess = 0;
            int retryAttempts = 10;

            for (int i = 0; i < retryAttempts; i++) {
                try {
                    var response = retryClient.get(failingUrl);
                    if (response.getStatusCode() == 200) {
                        retrySuccess++;
                    }
                } catch (Exception e) {
                    // 忽略异常，继续测试
                }
            }

            System.out.printf("无重试成功次数: %d/%d%n", noRetrySuccess, noRetryAttempts);
            System.out.printf("有重试成功次数: %d/%d%n", retrySuccess, retryAttempts);
            System.out.printf("重试提升成功率: %.2f%%%n",
                ((double)(retrySuccess - noRetrySuccess) / noRetryAttempts) * 100);

        } finally {
            noRetryClient.close();
            retryClient.close();
        }

        System.out.println();
    }

    /**
     * 并发性能对比
     */
    private static void concurrencyComparison() {
        System.out.println("4. 并发性能对比");
        System.out.println("=" + "=".repeat(50));

        // 普通客户端
        RestClient normalClient = RestClient.builder()
            .baseUrl("https://httpbin.org")
            .build();

        // 高并发客户端
        RestClient concurrentClient = RestClient.builder()
            .forHighConcurrency()
            .baseUrl("https://httpbin.org")
            .build();

        try {
            String testUrl = "/get";
            int threadCount = 20;
            int requestsPerThread = 5;

            // 测试普通客户端
            long normalTime = testConcurrency(normalClient, threadCount, requestsPerThread, "普通客户端");

            // 测试高并发客户端
            long concurrentTime = testConcurrency(concurrentClient, threadCount, requestsPerThread, "高并发客户端");

            System.out.printf("并发性能提升: %.2f%%%n",
                ((double)(normalTime - concurrentTime) / normalTime) * 100);

        } finally {
            normalClient.close();
            concurrentClient.close();
        }

        System.out.println();
    }

    /**
     * 内存使用对比
     */
    private static void memoryUsageComparison() {
        System.out.println("5. 内存使用对比");
        System.out.println("=" + "=".repeat(50));

        Runtime runtime = Runtime.getRuntime();

        // 基础客户端内存测试
        runtime.gc();
        long baseMemory = runtime.totalMemory() - runtime.freeMemory();

        RestClient basicClient = RestClient.create();
        var basicResponse = basicClient.get("https://httpbin.org/get");

        runtime.gc();
        long basicMemory = runtime.totalMemory() - runtime.freeMemory();
        basicClient.close();

        // 完整功能客户端内存测试
        runtime.gc();

        RestClient fullClient = RestClient.builder()
            .baseUrl("https://httpbin.org")
            .enableCompression(true)
            .enableRetry(true)
            .addExtension(new MonitoringExtension())
            .addExtension(new CacheExtension())
            .addExtension(new RetryExtension())
            .build();

        var fullResponse = fullClient.get("/get");

        runtime.gc();
        long fullMemory = runtime.totalMemory() - runtime.freeMemory();
        fullClient.close();

        System.out.printf("基础内存使用: %.2f KB%n", (basicMemory - baseMemory) / 1024.0);
        System.out.printf("完整功能内存使用: %.2f KB%n", (fullMemory - baseMemory) / 1024.0);
        System.out.printf("内存开销增加: %.2f%%%n",
            ((double)(fullMemory - basicMemory) / (basicMemory - baseMemory)) * 100);

        System.out.println();
    }

    /**
     * 并发测试辅助方法
     */
    private static long testConcurrency(RestClient client, int threadCount, int requestsPerThread, String name) {
        long startTime = System.currentTimeMillis();

        java.util.concurrent.ExecutorService executor =
            java.util.concurrent.Executors.newFixedThreadPool(threadCount);
        java.util.concurrent.CountDownLatch latch = new java.util.concurrent.CountDownLatch(threadCount);

        for (int i = 0; i < threadCount; i++) {
            executor.submit(() -> {
                try {
                    for (int j = 0; j < requestsPerThread; j++) {
                        var response = client.get("/get");
                        // 简单验证响应
                        if (!response.isSuccess()) {
                            log.warn("请求失败: {}", response.getStatusCode());
                        }
                    }
                } finally {
                    latch.countDown();
                }
            });
        }

        try {
            latch.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        long endTime = System.currentTimeMillis();
        long totalTime = endTime - startTime;

        System.out.printf("%s并发测试: %d线程 * %d请求 = %d总请求, 耗时: %dms%n",
            name, threadCount, requestsPerThread, threadCount * requestsPerThread, totalTime);

        executor.shutdown();
        return totalTime;
    }
}